<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>原理</title>
</head>
<body>
    <div id="box"></div>

    <div id="app">{{JSON.stringify(score)}}</div>

    <script src="./js/vue.js"></script>
    <script>
        var box = document.querySelector('#box');

        // vue之所以能做到响应式数据是因为把所有的值属性转化为存储器属性

        // 依据响应式属性原理模拟vue数据交互
        const person = {
            username:'kuiya',
            password:123456,
            sorce:{
                math:80,
                english:90,
                chinese:87
            }
        }
        box.innerHTML = person.username;

        // 1.错误示范，在改完属性值后没有了自己的参照物，没有原来的数据，进入一个死循环，解决方法是设置一个空对象来进行处理
        /* for(let key in person){
            Object.defineProperty(person,key,{
                get(){
                    return person[key]
                },
                set(newValue){
                    box.innerHTML = newValue;
                    person[key] = newValue;
                }
            })
        } */

        // 2.正确示范
        /* 在不影响原来数据的前提下进行遍历设置存储器属性，用新的对象代理原来对象 */
        const newPerson = {};
        for(let key in person){
            Object.defineProperty(newPerson,key,{
                /* 设置成存储器属性后就可以为所欲为 */
                get(){
                    return person[key]
                },
                set(newValue){
                    // 监听到值的修改则修改页面数据
                    box.innerHTML = newValue;
                    person[key] = newValue;
                }
            })
        }

        /* 
            * 在控制台修改username的值，页面在不刷新的情况下有所响应
            * 而vue实例中，数据挂载在vue的data属性下后，内部会自动遍历数据后把属性设置为存储器属性并挂载在一个新的空对象里
        
        */

        // 3.vue实例实现响应式属性
        const initData = {
            age:66,
            gender:'female',
            score:{
                math:79
            }
        }
        var vm = new Vue({
            el:'#app',
            // 实例化Vue时，内部自动遍历data下所有的属性，把所有属性变成getter&setter，并写入vm实例
            data:initData
        })

        /* 注意：以传统的对象添加属性的方式给vm添加的新属性，因为没有参与实例化，所以不是存储器属性，也就无法作为响应式属性来做到修改数据达到更新视图的目的 */

        // 4.vue实例化后的响应式属性设置
        // 4.1 错误示范
        // Vue.set(vm,'username','laotie');
        /* 注意对象不能是 Vue 实例，或者 Vue 实例的根数据对象，会报错 */

        // 4.2 
        Vue.set(vm.score,'english',87);
        /* 只能挂载在次级对象下 */

        // 4.3 默认写法
        vm.score.chinese = 90;
        /* 传统的属性添加无法做到修改数据后页面响应，要与4.2主要区分,要刷新只能通过实例的下$forceUpdate()强制刷新 */

        console.log(vm);

    </script>
</body>
</html>